package com.hemerasolutions.v2trainer.model.exercise.intensity;

import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import com.hemerasolutions.v2trainer.model.base.BaseModel;
import com.hemerasolutions.v2trainer.model.exercise.executions.AssociationET;
import com.hemerasolutions.v2trainer.model.exercise.executions.Execution;
import com.hemerasolutions.v2trainer.model.training.TrainingType;
import com.hemerasolutions.v2trainer.model.unit.intensity.IntensityUnit;

@Entity
public class IntensityTable  extends BaseModel {

	private static final long serialVersionUID = 1L;

    @Column( length = 1 )
    private int level;    
    
    @ManyToOne
    private IntensityExecution intensityExecution;
    
    @ManyToMany(fetch = FetchType.LAZY)
    private List<IntensityUnit> intensityUnits;
    
    @OneToMany(mappedBy="intensityTable" , cascade=CascadeType.ALL, fetch = FetchType.LAZY,orphanRemoval=true)
    private List<IntensityZone> intensitys;

    
    public static final int LEVEL_GENERAL 		= 0;
    public static final int LEVEL_SEDENTARY 	= 1;
    public static final int LEVEL_BEGINNER		= 2;
    public static final int LEVEL_MODERATELY 	= 3;
    public static final int LEVEL_TRAINED		= 4; 
    public static final int LEVEL_HIGHLY		= 5;

    
    public IntensityTable() {
		super();
		this.level = LEVEL_GENERAL;
		this.intensitys = new ArrayList<IntensityZone>();
		this.intensityUnits = new ArrayList<IntensityUnit>();
    }

    
    public IntensityTable(int level,IntensityExecution ie){
    	super();
    	this.id = null;
    	this.intensityExecution = ie;
    	this.level = level;
    	this.intensitys = new ArrayList<IntensityZone>();
    	this.intensityUnits = new ArrayList<IntensityUnit>();
    }
    
    public IntensityTable(IntensityTable other){
    	super();
    	this.id = null;
    	this.intensityExecution = other.intensityExecution;
    	this.level = other.level;
    	
    	this.intensitys = new ArrayList<IntensityZone>();
    	for(IntensityZone iz:other.intensitys){
    		this.intensitys.add(new IntensityZone(iz,this));
    	}
    	
    	this.intensityUnits = new ArrayList<IntensityUnit>();
    	for(IntensityUnit iu:other.intensityUnits){
    		this.intensityUnits.add(iu);
    	}
    	
    }

    
    public IntensityTable(IntensityTable other, IntensityExecution ie){
    	super();
    	this.id = null;
    	this.intensityExecution = ie;
    	this.level = other.level;
    	
    	this.intensitys = new ArrayList<IntensityZone>();
    	for(IntensityZone iz:other.intensitys){
    		this.intensitys.add(new IntensityZone(iz,this));
    	}
    	
    	this.intensityUnits = new ArrayList<IntensityUnit>();
    	for(IntensityUnit iu:other.intensityUnits){
    		this.intensityUnits.add(iu);
    	}
    	
    }
    
    
    public String getLevelName(){
    	switch (this.level) {
		case LEVEL_GENERAL:
			return 	"LEVEL_GENERAL";
		case LEVEL_SEDENTARY:
			return 	"LEVEL_SEDENTARY";
		case LEVEL_BEGINNER:
			return 	"LEVEL_BEGINNER";
		case LEVEL_MODERATELY:
			return 	"LEVEL_MODERATELY";
		case LEVEL_TRAINED:
			return 	"LEVEL_TRAINED";
		case LEVEL_HIGHLY:
			return 	"LEVEL_HIGHLY";
		default:
			return 	"LEVEL_GENERAL";
		}
    }
    

	public void upIntensityZone(IntensityZone iz){

		int i = intensitys.indexOf(iz);
		if(iz.getPosition() != 0 ){
			intensitys.add(i - 1,intensitys.remove(i));	
		}

		this.refresh();
	}

	public void downIntensityZone(IntensityZone iz){
		int i = intensitys.indexOf(iz);
		if(iz.getPosition() != 0 ){
			intensitys.add(i + 1,intensitys.remove(i));	
		}

		this.refresh();
	}	
	
	
	public IntensityZone addIntensityZone(){

		this.intensitys.add(new IntensityZone(this));
		return this.intensitys.get(this.intensitys.size() - 1);
		
	}
	
	
	public IntensityUnit addIntensityUnit(Execution ex, TrainingType tt, String unitName){
		
		
		for(AssociationET assoc: ex.getAssociationETs()){
    		if(assoc.getTrainingType().getId() == tt.getId()){
        		for( IntensityUnit iu: assoc.getIntensityUnits()){
        			if(iu.getName().equals(unitName)){
        		        this.getIntensityUnits().add(iu);
        		        for(IntensityZone iz:this.getIntensitys()){
        		        	iz.getIntensitys().add(new Intensity(iu,iz));
        		        }
        		        return iu;
        			}
        		}
    		}
    	}		
    	
		return null;
	}
	
	public void refresh() {
		for(int i = 0; i < intensitys.size(); i++ ){
			IntensityZone iz = intensitys.get(i);
			iz.setPosition(i);
		}
	}

	
	public boolean isEmpty(){

		if(intensitys == null || intensitys.isEmpty()){
			return true;
		}
		
		return false;
	}
	    
    
    
	public IntensityExecution getIntensityExecution() {
		return intensityExecution;
	}



	public void setIntensityExecution(IntensityExecution intensityExecution) {
		this.intensityExecution = intensityExecution;
	}



	public List<IntensityZone> getIntensitys() {
		return intensitys;
	}

	public void setIntensitys(List<IntensityZone> intensitys) {
		this.intensitys = intensitys;
	}

	public List<IntensityUnit> getIntensityUnits() {
		return intensityUnits;
	}

	public void setIntensityUnits(List<IntensityUnit> intensityUnits) {
		this.intensityUnits = intensityUnits;
	}

	
	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
	}

	public void copyIntensityTable(IntensityTable other) {

		this.intensitys = new ArrayList<IntensityZone>();
		this.intensityUnits = new ArrayList<IntensityUnit>();
		for(IntensityZone iz:other.intensitys){
			this.intensitys.add(new IntensityZone(iz,this));
		}
		for(IntensityUnit iu:other.intensityUnits){
			this.intensityUnits.add(iu);
		}
		
	}


	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime
				* result
				+ ((intensityExecution == null) ? 0 : intensityExecution
						.hashCode());
		result = prime * result + level;
		result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
		return result;
	}


	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		IntensityTable other = (IntensityTable) obj;
		if (id == null) {
			if (other.id != null) {
				return false;
			}
		} else if (!id.equals(other.id)) {
			return false;
		}
		if (intensityExecution == null) {
			if (other.intensityExecution != null) {
				return false;
			}
		} else if (!intensityExecution.equals(other.intensityExecution)) {
			return false;
		}
		if (level != other.level) {
			return false;
		}
		if (uuid == null) {
			if (other.uuid != null) {
				return false;
			}
		} else if (!uuid.equals(other.uuid)) {
			return false;
		}
		return true;
	}


	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "IntensityTable [id=" + id + ", level=" + level
				+ ", intensityExecution=" + intensityExecution + ", uuid="
				+ uuid + "]";
	}
}
